import {
  AntFilterValue as FilterValue,
  AntSorterResult as SorterResult,
  AntTablePaginationConfig as TablePaginationConfig,
  AntTableProps as TableProps,
} from "fidesui";
import { useCallback, useMemo, useState } from "react";

import { DEFAULT_PAGE_SIZES } from "../constants";
import type {
  AntTableHookConfig,
  SelectionState,
  TableStateWithHelpers,
} from "./types";

/**
 * Hook for Ant Design table integration with table state management
 *
 * @param tableState - Table state from useTableState hook
 * @param config - Ant Design specific configuration
 * @returns Ant Design table props and utilities
 *
 * @example
 * ```tsx
 * const tableState = useTableState<MyColumnKeys>();
 * const { data, isLoading } = useGetMyDataQuery(tableState.queryParams);
 *
 * const {
 *   tableProps,
 *   selectionProps,
 *   selectedRows,
 *   resetSelections
 * } = useAntTable(tableState, {
 *   enableSelection: true,
 *   getRowKey: (record) => record.id,
 *   dataSource: data?.items || [],
 *   totalRows: data?.total || 0,
 *   isLoading
 * });
 *
 * return <Table {...tableProps} rowSelection={selectionProps} />;
 * ```
 */
export const useAntTable = <TData, TSortKey extends string = string>(
  tableState: TableStateWithHelpers<TSortKey>,
  config: AntTableHookConfig<TData> = {},
) => {
  const {
    enableSelection = false,
    getRowKey,
    bulkActions,
    isLoading = false,
    isFetching = false,
    dataSource = [],
    totalRows = 0,
    currentPage,
    pageSize: configPageSize,
    customTableProps = {},
  } = config;

  // Default rowKey function that prefers 'id' then 'key' properties
  const defaultGetRowKey = useCallback((record: TData): string => {
    if (record && typeof record === "object") {
      const recordObj = record as Record<string, unknown>;
      if (recordObj.id) {
        return String(recordObj.id);
      }
      if (recordObj.key) {
        return String(recordObj.key);
      }
    }
    // Fallback to string representation
    return String(record);
  }, []);

  const rowKeyFunction = getRowKey || defaultGetRowKey;

  // Selection state management (simplified to match original working pattern)
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  const [selectedRows, setSelectedRows] = useState<TData[]>([]);

  const resetSelections = useCallback(() => {
    setSelectedRowKeys([]);
    setSelectedRows([]);
  }, []);

  const selectionState: SelectionState<TData> = useMemo(
    () => ({
      selectedRowKeys,
      selectedRows,
      resetSelections,
    }),
    [selectedRowKeys, selectedRows, resetSelections],
  );

  // Selection props for Ant Design Table (simplified to match original working pattern)
  const selectionProps = useMemo(() => {
    if (!enableSelection) {
      return undefined;
    }

    return {
      selectedRowKeys,
      onChange: (newSelectedRowKeys: React.Key[], newSelectedRows: TData[]) => {
        setSelectedRowKeys(newSelectedRowKeys);
        setSelectedRows(newSelectedRows);
      },
    };
  }, [enableSelection, selectedRowKeys]);

  // Table change handler
  const handleTableChange = useCallback(
    (
      pagination: TablePaginationConfig,
      filters: Record<string, FilterValue | null>,
      sorter: SorterResult<TData> | SorterResult<TData>[],
    ) => {
      // Check if this is just a pagination change (page or pageSize changed)
      // Handle undefined values defensively to avoid false positives
      const currentPageFromPagination =
        pagination.current ?? tableState.pageIndex;
      const pageSizeFromPagination = pagination.pageSize ?? tableState.pageSize;
      const isPaginationChange =
        currentPageFromPagination !== tableState.pageIndex ||
        pageSizeFromPagination !== tableState.pageSize;

      // Handle pagination with tableState
      if (isPaginationChange) {
        if (pagination.current && pagination.current !== tableState.pageIndex) {
          tableState.updatePageIndex(pagination.current);
        }
        if (
          pagination.pageSize &&
          pagination.pageSize !== tableState.pageSize
        ) {
          tableState.updatePageSize(pagination.pageSize);
        }
      } else {
        // Only update filters when it's not a pagination change
        // The pagination reset is handled by updateFilters and updateSorting
        tableState.updateFilters(filters || {});
      }

      // Handle sorting with tableState (only if sorting actually changed)
      const newSortKey =
        sorter && !Array.isArray(sorter)
          ? (sorter.field as TSortKey)
          : undefined;
      const newSortOrder =
        sorter && !Array.isArray(sorter) && sorter.order !== null
          ? sorter.order
          : undefined;

      // Only update sorting if this is not just a pagination change
      // The pagination reset is handled by updateSorting
      if (!isPaginationChange) {
        tableState.updateSorting(newSortKey, newSortOrder);
      }
    },
    [tableState],
  );

  // Pagination configuration
  const paginationProps = useMemo(
    () => ({
      current: currentPage ?? tableState.pageIndex,
      pageSize: configPageSize ?? tableState.pageSize,
      total: totalRows,
      showSizeChanger: tableState.paginationConfig?.showSizeChanger ?? true,
      pageSizeOptions:
        tableState.paginationConfig?.pageSizeOptions?.map(String) ??
        DEFAULT_PAGE_SIZES,
    }),
    [
      currentPage,
      tableState.pageIndex,
      configPageSize,
      tableState.pageSize,
      totalRows,
      tableState.paginationConfig,
    ],
  );

  // Main table props (memoized)
  const tableProps: Partial<TableProps<TData>> = useMemo(
    () => ({
      dataSource,
      loading: isLoading || isFetching,
      pagination: paginationProps,
      onChange: handleTableChange,
      rowKey: rowKeyFunction,
      scroll: { x: "max-content", scrollToFirstRowOnChange: true },
      size: "small" as const,
      bordered: true,
      ...customTableProps,
    }),
    [
      dataSource,
      isLoading,
      isFetching,
      paginationProps,
      handleTableChange,
      rowKeyFunction,
      customTableProps,
    ],
  );

  // Selected data helpers (simplified to match original working pattern)
  const selectedKeys = selectedRowKeys.map(String);
  const hasSelectedRows = selectedRows.length > 0;

  // Bulk actions helpers
  const getBulkActionProps = useCallback(
    (actionKey: string) => {
      const action = bulkActions?.actions.find((a) => a.key === actionKey);
      if (!action) {
        return { disabled: true, loading: false };
      }

      return {
        disabled:
          !hasSelectedRows ||
          (action.disabled ? action.disabled(selectedRows) : false),
        loading: action.loading || false,
        onClick: () => action.onClick(selectedRows),
      };
    },
    [bulkActions, hasSelectedRows, selectedRows],
  );

  return useMemo(
    () => ({
      // Main table props
      tableProps,

      // Selection
      selectionProps,
      selectionState,
      selectedRows,
      selectedKeys,
      hasSelectedRows,
      resetSelections,

      // Bulk actions
      getBulkActionProps,

      // Utilities
      isLoadingOrFetching: isLoading || isFetching,
      hasData: dataSource.length > 0,
    }),
    [
      tableProps,
      selectionProps,
      selectionState,
      selectedRows,
      selectedKeys,
      hasSelectedRows,
      resetSelections,
      getBulkActionProps,
      isLoading,
      isFetching,
      dataSource.length,
    ],
  );
};
